package io.kimmking.auth2.config;

//import io.kimmking.dubbo.common.unit.ResponseResult;
import io.kimmking.auth2.unit.ResponseResultV1;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * 配置资源服务
 */
@Configuration
@Slf4j
//开启资源服务
@EnableResourceServer
//开启注解形式控制
//@EnableGlobalMethodSecurity(prePostEnabled = true)
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    @Autowired
    private TokenStore tokenStore;


    /**
     * 配置接口访问策略信息
     * @param http
     * @throws Exception
     */
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                // /test可以匿名访问
                .antMatchers("/test",
                        "/swagger-ui.html",
                        "/v2/api-docs").permitAll()
                //任何请求都需要身份认证
                .and()
                .authorizeRequests()
                .antMatchers("/**").authenticated()
                .and()
                //配置异常处理器
                .exceptionHandling()
                .authenticationEntryPoint(this::commence)

                .and()
                .csrf()
                .disable();
    }

    /**
     * 配置资源服务安全
     * 用户权限等信息从 tokenStore 读取，及异常处理
     * @param resources
     * @throws Exception
     */
    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.tokenStore(tokenStore)
                .stateless(false)
//                .accessDeniedHandler(this::commence)
                .authenticationEntryPoint(this::commence);
    }

    /**
     * 自定义来自于资源管理器的异常处理器
     * @param var1
     * @param var2
     * @param var3
     * @throws IOException
     */
    public void commence(HttpServletRequest var1,
                         HttpServletResponse var2,
                         AuthenticationException var3) throws IOException, ServletException {

        log.error("auth from ResourceServer failed : {}", var3.getMessage());
        var2.setContentType("application/json;charset=utf-8");
        PrintWriter out;

        ResponseResultV1 responseEntity;

        if(var3 instanceof InsufficientAuthenticationException) {
            responseEntity = ResponseResultV1.failed("身份验证异常，令牌已过期或未带令牌");
        } else {
            responseEntity = ResponseResultV1.failed(var3.getMessage());
        }
        out = var2.getWriter();
        out.write(responseEntity.toString());
        out.flush();
        out.close();
    }
}
